/*
 *    Copyright © OpenAtom Foundation.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.inspur.edp.bef.core.be;

import com.inspur.edp.bef.api.action.IBefCallContext;
import com.inspur.edp.bef.api.be.BufferClearingType;
import com.inspur.edp.bef.api.be.IBEContext;
import com.inspur.edp.bef.api.be.IBENodeEntityContext;
import com.inspur.edp.bef.api.be.IBusinessEntity;
import com.inspur.edp.bef.api.lcp.IStandardLcp;
import com.inspur.edp.bef.api.lcp.ResponseContext;
import com.inspur.edp.bef.api.services.IBELogger;
import com.inspur.edp.bef.core.DotNetToJavaStringHelper;
import com.inspur.edp.bef.core.LcpUtil;
import com.inspur.edp.bef.core.action.AuthorityUtil;
import com.inspur.edp.bef.core.action.authorityinfo.BefAuthorityInfo;
import com.inspur.edp.bef.core.action.base.ActionUtil;
import com.inspur.edp.bef.core.action.base.BEEntityActionExecutor;
import com.inspur.edp.bef.core.changeset.BEChangesetManager;
import com.inspur.edp.bef.core.lock.LockService;
import com.inspur.edp.bef.core.logger.BefLogger;
import com.inspur.edp.bef.core.scope.BefScopeStack;
import com.inspur.edp.bef.core.session.BEFuncSessionBase;
import com.inspur.edp.bef.core.session.FuncSessionManager;
import com.inspur.edp.commonmodel.core.variable.VarBufferManager;
import com.inspur.edp.cef.api.RefObject;
import com.inspur.edp.cef.api.changeListener.IChangeHandlerContext;
import com.inspur.edp.cef.api.dataType.action.IDataTypeActionExecutor;
import com.inspur.edp.cef.api.dataType.base.IAccessorCreator;
import com.inspur.edp.cef.entity.changeset.AddChangeDetail;
import com.inspur.edp.cef.spi.entity.resourceInfo.EntityResInfo;
import com.inspur.edp.cef.spi.entity.resourceInfo.ModelResInfo;
import com.inspur.edp.cef.api.scope.ICefScopeNodeParameter;
import com.inspur.edp.cef.entity.changeset.ChangeDetailMerger;
import com.inspur.edp.cef.entity.changeset.ChangeType;
import com.inspur.edp.cef.entity.changeset.IChangeDetail;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.cef.spi.entity.CefEntityContext;
import com.inspur.edp.cef.variable.api.data.IVariableData;
import java.util.Map;
import java.util.Objects;

public abstract class BEContext extends CefEntityContext implements IBEContext,
		IChangeHandlerContext
{

		//region Constructor

	protected BEContext()
	{
	}


		//endregion


		//region Current变更&数据
	private IAccessorCreator privateAccessorCreator;
	public final IAccessorCreator getAccessorCreator()
	{
		return privateAccessorCreator;
	}
	public final void setAccessorCreator(IAccessorCreator value)
	{
		privateAccessorCreator = value;
	}

//	private BEBufferManager privateBufferManager;
//	public final BEBufferManager getBufferManager()
//	{
//		return privateBufferManager;
//	}
//	public final void setBufferManager(BEBufferManager value)
//	{
//		privateBufferManager = value;
//	}

//	private BEChangesetManager privateChangesetManager;
//	public final BEChangesetManager getChangesetManager()
//	{
//		return privateChangesetManager;
//	}
//	public final void setChangesetManager(BEChangesetManager value)
//	{
//		privateChangesetManager = value;
//	}
	public final IBeBufferChangeManager getBufferChangeManager() {return getSessionItem().getBufferChangeManager(); }

	/** 
	 Current数据临时变更集
	 
	*/
	@Override
	public IChangeDetail getCurrentTemplateChange() {
	  return getBufferChangeManager().getCurrentTemplateChange(getID());}

	//监听收集的变更, 需要合并到InnerChange中,
	//CurrentTemplateChange(TempCurrentChange)既包括ListenerChange也包括来自modify传入的变更;
	 public IChangeDetail getListenerChange(){
     return getBufferChangeManager().getListenerChange(getID());
   }
	 public void setListenerChange(IChangeDetail value){
     getBufferChangeManager().initListenerChange(value);
   }

	 @Override
   public IChangeDetail getChangeDetail() {return getListenerChange();}
	 @Override
   public void setChangeDetail(IChangeDetail value){setListenerChange(value);}

	//public IChangeDetail ChangeFromModify { get; set; }

	@Override
  public IChangeDetail getCurrentChange(){return getBufferChangeManager().getCurrentChange(getID());}

	/** 
	 一次请求内未提交数据
	 
	*/
	private IEntityData privateCurrentData;
	@Override
  public final IEntityData getCurrentData() {
		return privateCurrentData;
	}

	public final void setCurrentData(IEntityData value)
	{
		privateCurrentData = value;
	}

	 @Override
	 public IEntityData getData(){return getCurrentData();}
	 @Override
	 public void setData(IEntityData value){setCurrentData(value);}

		//endregion


		//region Transaction变更&数据
	/** 
	 已提交数据
	 
	*/
	private IEntityData privateTransactionData;
	@Override
  public final IEntityData getTransactionData()
	{
		return privateTransactionData;
	}
	public final void setTransactionData(IEntityData value)
	{
		privateTransactionData = value;
	}

	@Override
  public IChangeDetail getTransactionalChange() {return getBufferChangeManager().getTransactionChange(getID());}

  @Override
	public IChangeDetail getCurrentTransactionalChange() {
		IChangeDetail currentChange = getCurrentChange();
		if (currentChange == null) {
			return getTransactionalChange();
		}
		IChangeDetail transactionalChange = getTransactionalChange();
		if (transactionalChange == null) {
			return currentChange;
		}
		if(transactionalChange.getChangeType() == ChangeType.Added
				&& currentChange.getChangeType() != ChangeType.Deleted){
			return new AddChangeDetail(getCurrentData());
		}
		ActionUtil.getRootBEContext(this).suspendChangeListener();
		try {
			return ChangeDetailMerger
					.mergeChangeDetail(currentChange, transactionalChange.clone());
		} finally {
			ActionUtil.getRootBEContext(this).resumeChangeListener();
		}
	}

	 @Override
   public BufferClearingType getBufferClearingType(){return getSessionItem().getBufferClearingType();}
	 @Override
   public void setBufferClearingType(BufferClearingType value){getSessionItem().setBufferClearingType(value);}

		//endregion

		//region Original变更&数据
	/**原始数据*/
	private IEntityData privateOriginalData;
	@Override
  public final IEntityData getOriginalData()
	{
		return privateOriginalData;
	}
	public final void setOriginalData(IEntityData value)
	{
		privateOriginalData = value;
	}

		//endregion

		//region 数据状态
	private BEChangesetManager privateChangeManager;
	public final BEChangesetManager getChangeManager()
	{
		return privateChangeManager;
	}
	public final void setChangeManager(BEChangesetManager value)
	{
		privateChangeManager = value;
	}

	/** 
	 当前数据对应的DataID
	 
	*/
	@Override
  public String getID(){
		return this.getDataType().getID();
	}

	@Override
  public IBusinessEntity getBizEntity() {
		return (IBusinessEntity)this.getDataType();
	}

	/** 
	 是否有数据
	 
	*/
	@Override
  public boolean hasData() {return getCurrentData() != null || getTransactionData() != null || getOriginalData() != null;}

	public boolean hasChange() {return getCurrentChange() != null || getCurrentTemplateChange() != null || getTransactionalChange() != null;}

	/**是否加锁*/
	@Override
  public boolean isLocked() {return isLocked(new RefObject<String>(""));}

	public final boolean isLocked(RefObject<String> userName) {
		userName.argvalue = null;
		return ((IBEContext)this).isNew() || LockService.getInstance().getLockState(getBizEntity().getBEType(), getID(), userName);
	}

	@Override
  public boolean isDeleted() {
		IChangeDetail currentChange = getCurrentChange();
		if(currentChange != null && currentChange.getChangeType() == ChangeType.Deleted){
			return true;
		}
		IChangeDetail transactionalChange = getTransactionalChange();
		if(transactionalChange != null && transactionalChange.getChangeType() == ChangeType.Deleted){
			return true;
		}
		return false;
	}

	@Override
  public final boolean isNew()
	{
		IChangeDetail currentChange = getCurrentChange();
		if(currentChange != null && currentChange.getChangeType() == ChangeType.Added){
			return true;
		}
		IChangeDetail transactionalChange = getTransactionalChange();
		if(transactionalChange != null && transactionalChange.getChangeType() == ChangeType.Added) {
			return true;
		}
		return false;
	}

		//endregion



		//region i18n
	private ModelResInfo privateModelResInfo;
	@Override
  public final ModelResInfo getModelResInfo()
	{
		return privateModelResInfo;
	}
	public final void setModelResInfo(ModelResInfo value)
	{
		privateModelResInfo = value;
	}

	public final EntityResInfo getEntityResourceInfos(String nodeCode)
	{
		ModelResInfo ModelResInfo = getModelResInfo();
		return ModelResInfo == null ? null: ModelResInfo.getCustomResource(nodeCode);
	}

	public final EntityResInfo getCurrentEntityResourceInfos()
	{
		return getEntityResourceInfos(getCode());
	}

	@Override
  public final String getEntityI18nName()
	{
		return getCurrentEntityResourceInfos().getDisplayName();
	}

	@Override
  public final String getPropertyI18nName(String labelID)
	{
EntityResInfo infos= getCurrentEntityResourceInfos();
		String result = infos == null ? null : infos.getPropertyDispalyName(labelID);
		if (DotNetToJavaStringHelper.isNullOrEmpty(result))
		{
			result = labelID;
		}
		return result;
	}

	@Override
  public final String getRefPropertyI18nName(String labelID, String refLabelID)
	{
    EntityResInfo  infos = getCurrentEntityResourceInfos();
    String result = infos  == null ? null : infos.getAssoRefPropertyDisplay(labelID, refLabelID);
		if (DotNetToJavaStringHelper.isNullOrEmpty(result))
		{
			result = refLabelID;
		}
		return result;
	}

	@Override
  public final String getEnumValueI18nDisplayName(String labelID, String enumKey)
	{
		return getCurrentEntityResourceInfos().getEnumPropertyDispalyValue(labelID, enumKey);

	}

	@Override
  public final String getUniqueConstraintMessage(String conCode)
	{
		return getCurrentEntityResourceInfos().getUniqueConstraintMessage(conCode);
	}


		//endregion


		//region 其他
  @Override
    public <T> IDataTypeActionExecutor<T> getActionExecutor() {
    return new BEEntityActionExecutor<T>(this);
	}

	@Override
  public IBENodeEntityContext getParentContext() {return null;}

	private BEFuncSessionBase privateSessionItem;
	public final BEFuncSessionBase getSessionItem() {
		return privateSessionItem;
	}
	final void setSessionItem(BEFuncSessionBase value) {
		privateSessionItem = value;
	}
		//endregion


		//region Scope
	@Override
  public final void addScopeParameter(ICefScopeNodeParameter parameter) {
		Objects.requireNonNull(parameter);
		getSessionItem().getFuncSession().getScopeManager().addScopeParameter(parameter);
	}

		//endregion


		//region 内部变更&消息
	private ResponseContext privateResponse;
	public final ResponseContext getResponse()
	{
		return privateResponse;
	}
	public final void setResponse(ResponseContext value)
	{
		privateResponse = value;
	}

	//IDtmAssemblerFactory IBEContext.DtmAssemblerFactory => DtmAssemblerFactory;

	@Override
  public final IBELogger getLogger()
	{
		return new BefLogger();
	}

	@Override
  public final IStandardLcp getLcp(String config)
	{
		return LcpUtil.getLcp(config);
	}

	//public IStandardLcp getLcp(string config, bool newSession)
	//{
	//    return LcpUtil.getLcp(config,newSession);
	//}

	@Override
  public final void checkDataAuthority(String actionCode)
	{
		AuthorityUtil.checkDataAuthority(this);
	}

	//TODO:[cef] 找前端商量一下定位到行的message主表子表如何标识
	private String privateCode;
	@Override
  public final String getCode()
	{
		return privateCode;
	}
	public final void setCode(String value)
	{
		privateCode = value;
	}

		//endregion


		//region 变量

	private VarBufferManager privateVarBufferManager;
	public final VarBufferManager getVarBufferManager()
	{
		return privateVarBufferManager;
	}
	public final void setVarBufferManager(VarBufferManager value)
	{
		privateVarBufferManager = value;
	}

	public IVariableData getVariables() {
		return getVarBufferManager().getCurrentData();
	}

	@Override
	public IBefCallContext getCallContext(){
		return getSessionItem().getCallContext();
	}
		//endregion
}
